#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <pthread.h>

// 君正SDK头文件
#include <imp/imp_log.h>
#include <imp/imp_common.h>
#include <imp/imp_system.h>
#include <imp/imp_framesource.h>
#include <imp/imp_encoder.h>
#include <imp/imp_isp.h>

// RTSP相关头文件
#include "rtspservice.h"
#include "rtputils.h"
#include "ringfifo.h"

// 君正相关配置
#define FS_CHN_NUM 2
#define CH0_INDEX 0
#define CH1_INDEX 1
#define CHN0_EN 1
#define CHN1_EN 1

// 视频参数配置
#define VIDEO_WIDTH 1920
#define VIDEO_HEIGHT 1080
#define VIDEO_FPS 25
#define VIDEO_BITRATE 2000 // kbps

// 全局变量
struct ringbuf ringinfo;
int stop = 1;
struct chn_conf chn[FS_CHN_NUM];
IMPSensorInfo sensor_info[1];

// 函数声明
void PrefsInit();
void RTP_port_pool_init(int port);
void EventLoop(int s32MainFd);
int sample_system_init();
int sample_system_exit();
int sample_framesource_init();
int sample_framesource_exit();
int sample_encoder_init();
int sample_encoder_exit();
int sample_framesource_streamon();
int sample_framesource_streamoff();
int IngenicPutH264DataToBuffer(IMPEncoderStream *stream);

// 系统初始化函数
int sample_system_init()
{
    int ret;
    
    // 初始化IMP系统
    ret = IMP_System_Init();
    if (ret < 0) {
        IMP_LOG_ERR("IMP_System_Init() failed
");
        return -1;
    }
    
    // 打开ISP模块
    ret = IMP_ISP_Open();
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_Open() failed
");
        return -1;
    }
    
    // 配置传感器信息（根据实际硬件配置修改）
    memset(&sensor_info[0], 0, sizeof(IMPSensorInfo));
    sensor_info[0].sensorId = 0;
    strncpy(sensor_info[0].sensorName, "gc5603", sizeof(sensor_info[0].sensorName));
    sensor_info[0].i2cAddr = 0x31;
    sensor_info[0].i2cAdapter = 0;
    
    // 添加传感器
    ret = IMP_ISP_AddSensor(IMPVI_MAIN, &sensor_info[0]);
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_AddSensor() failed
");
        return -1;
    }
    
    // 使能传感器
    ret = IMP_ISP_EnableSensor(IMPVI_MAIN, &sensor_info[0]);
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_EnableSensor() failed
");
        return -1;
    }
    
    // 使能ISP调试
    ret = IMP_ISP_EnableTuning();
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_EnableTuning() failed
");
        return -1;
    }
    
    return 0;
}

// 系统退出函数
int sample_system_exit()
{
    int ret;
    
    // 关闭ISP调试
    ret = IMP_ISP_DisableTuning();
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_DisableTuning() failed
");
    }
    
    // 禁用传感器
    ret = IMP_ISP_DisableSensor(IMPVI_MAIN, &sensor_info[0]);
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_DisableSensor() failed
");
    }
    
    // 删除传感器
    ret = IMP_ISP_DelSensor(IMPVI_MAIN, &sensor_info[0]);
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_DelSensor() failed
");
    }
    
    // 关闭ISP模块
    ret = IMP_ISP_Close();
    if (ret < 0) {
        IMP_LOG_ERR("IMP_ISP_Close() failed
");
    }
    
    // 退出IMP系统
    ret = IMP_System_Exit();
    if (ret < 0) {
        IMP_LOG_ERR("IMP_System_Exit() failed
");
    }
    
    return 0;
}

// FrameSource初始化函数
int sample_framesource_init()
{
    int ret, i;
    
    // 配置通道0（主通道）
    chn[CH0_INDEX].index = CH0_INDEX;
    chn[CH0_INDEX].enable = CHN0_EN;
    chn[CH0_INDEX].payloadType = IMP_ENC_PROFILE_AVC_MAIN;
    
    // 设置通道0属性
    chn[CH0_INDEX].fs_chn_attr.pixFmt = PIX_FMT_YUV420P;
    chn[CH0_INDEX].fs_chn_attr.nWidth = VIDEO_WIDTH;
    chn[CH0_INDEX].fs_chn_attr.nHeight = VIDEO_HEIGHT;
    chn[CH0_INDEX].fs_chn_attr.nMaxFps = VIDEO_FPS;
    chn[CH0_INDEX].fs_chn_attr.nBufCnt = 4;
    
    // 配置通道1（可用于OSD或其他处理）
    chn[CH1_INDEX].index = CH1_INDEX;
    chn[CH1_INDEX].enable = CHN1_EN;
    chn[CH1_INDEX].payloadType = IMP_ENC_PROFILE_AVC_MAIN;
    
    // 设置通道1属性（降低分辨率用于OSD）
    chn[CH1_INDEX].fs_chn_attr.pixFmt = PIX_FMT_YUV420P;
    chn[CH1_INDEX].fs_chn_attr.nWidth = VIDEO_WIDTH;
    chn[CH1_INDEX].fs_chn_attr.nHeight = VIDEO_HEIGHT;
    chn[CH1_INDEX].fs_chn_attr.nMaxFps = VIDEO_FPS;
    chn[CH1_INDEX].fs_chn_attr.nBufCnt = 4;
    
    // 创建FrameSource通道
    for (i = 0; i < FS_CHN_NUM; i++) {
        if (chn[i].enable) {
            ret = IMP_FrameSource_CreateChn(chn[i].index, &chn[i].fs_chn_attr);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_FrameSource_CreateChn(%d) failed
", chn[i].index);
                return -1;
            }
            
            // 设置通道属性
            ret = IMP_FrameSource_SetChnAttr(chn[i].index, &chn[i].fs_chn_attr);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_FrameSource_SetChnAttr(%d) failed
", chn[i].index);
                return -1;
            }
            
            // 设置Cell信息
            chn[i].framesource_chn.devID = DEV_ID_FS;
            chn[i].framesource_chn.chnID = chn[i].index;
            chn[i].framesource_chn.devID = DEV_ID_FS;
        }
    }
    
    return 0;
}

// FrameSource退出函数
int sample_framesource_exit()
{
    int ret, i;
    
    for (i = 0; i < FS_CHN_NUM; i++) {
        if (chn[i].enable) {
            ret = IMP_FrameSource_DestroyChn(chn[i].index);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_FrameSource_DestroyChn(%d) failed
", chn[i].index);
                return -1;
            }
        }
    }
    
    return 0;
}

// 编码器初始化函数
int sample_encoder_init()
{
    int ret, i, chnNum;
    IMPEncoderChnAttr channel_attr;
    
    for (i = 0; i < FS_CHN_NUM; i++) {
        if (chn[i].enable) {
            // 设置编码器Cell信息
            chn[i].imp_encoder.devID = DEV_ID_ENCODER;
            chn[i].imp_encoder.chnID = chn[i].index;
            
            chnNum = chn[i].index;
            
            // 设置默认编码参数
            memset(&channel_attr, 0, sizeof(IMPEncoderChnAttr));
            channel_attr.type = IMP_ENC_H264;
            channel_attr.picWidth = chn[i].fs_chn_attr.nWidth;
            channel_attr.picHeight = chn[i].fs_chn_attr.nHeight;
            channel_attr.frmRateNum = VIDEO_FPS;
            channel_attr.frmRateDen = 1;
            channel_attr.bufSize = 1024 * 1024; // 1MB缓冲区
            channel_attr.rcMode = IMP_ENC_RC_MODE_CBR;
            channel_attr.outBitRate = VIDEO_BITRATE;
            
            // 创建编码通道
            ret = IMP_Encoder_CreateChn(chnNum, &channel_attr);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_Encoder_CreateChn(%d) failed
", chnNum);
                return -1;
            }
            
            // 注册通道到Group
            ret = IMP_Encoder_RegisterChn(chn[i].index, chnNum);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_Encoder_RegisterChn(%d, %d) failed
", chn[i].index, chnNum);
                return -1;
            }
        }
    }
    
    return 0;
}

// 编码器退出函数
int sample_encoder_exit()
{
    int ret, i, chnNum;
    IMPEncoderChnStat chn_stat;
    
    for (i = 0; i < FS_CHN_NUM; i++) {
        if (chn[i].enable) {
            chnNum = chn[i].index;
            
            // 查询通道状态
            ret = IMP_Encoder_Query(chnNum, &chn_stat);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_Encoder_Query(%d) failed
", chnNum);
                return -1;
            }
            
            // 反注册通道
            ret = IMP_Encoder_UnRegisterChn(chnNum);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_Encoder_UnRegisterChn(%d) failed
", chnNum);
                return -1;
            }
            
            // 销毁编码通道
            ret = IMP_Encoder_DestroyChn(chnNum);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_Encoder_DestroyChn(%d) failed
", chnNum);
                return -1;
            }
        }
    }
    
    return 0;
}

// 开始视频流
int sample_framesource_streamon()
{
    int ret, i;
    
    for (i = 0; i < FS_CHN_NUM; i++) {
        if (chn[i].enable) {
            ret = IMP_FrameSource_EnableChn(chn[i].index);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_FrameSource_EnableChn(%d) failed
", chn[i].index);
                return -1;
            }
            
            // 开始接收编码图像
            ret = IMP_Encoder_StartRecvPic(chn[i].index);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_Encoder_StartRecvPic(%d) failed
", chn[i].index);
                return -1;
            }
        }
    }
    
    return 0;
}

// 停止视频流
int sample_framesource_streamoff()
{
    int ret, i;
    
    for (i = 0; i < FS_CHN_NUM; i++) {
        if (chn[i].enable) {
            // 停止接收编码图像
            ret = IMP_Encoder_StopRecvPic(chn[i].index);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_Encoder_StopRecvPic(%d) failed
", chn[i].index);
                return -1;
            }
            
            // 禁用FrameSource通道
            ret = IMP_FrameSource_DisableChn(chn[i].index);
            if (ret < 0) {
                IMP_LOG_ERR("IMP_FrameSource_DisableChn(%d) failed
", chn[i].index);
                return -1;
            }
        }
    }
    
    return 0;
}

// 将H264数据放入缓冲区
int IngenicPutH264DataToBuffer(IMPEncoderStream *stream)
{
    int i;
    int frame_type = 0;
    
    // 判断帧类型
    if (stream->pack[0].type == IMP_ENC_PIC_TYPE_I) {
        frame_type = 1; // I帧
    } else if (stream->pack[0].type == IMP_ENC_PIC_TYPE_P) {
        frame_type = 0; // P帧
    }
    
    // 将数据放入环形缓冲区
    for (i = 0; i < stream->packCount; i++) {
        if (stream->pack[i].len > 0) {
            ringbuffer_write(&ringinfo, stream->pack[i].virAddr, stream->pack[i].len, frame_type);
        }
    }
    
    return 0;
}

// 编码线程函数
void *EncodeThread(void *p)
{
    int ret;
    IMPEncoderStream stream;
    
    while (stop) {
        // 查询编码数据
        ret = IMP_Encoder_PollingStream(CH0_INDEX, 1000);
        if (ret < 0) {
            continue;
        }
        
        // 获取编码流
        memset(&stream, 0, sizeof(IMPEncoderStream));
        ret = IMP_Encoder_GetStream(CH0_INDEX, &stream, 1);
        if (ret < 0) {
            continue;
        }
        
        // 处理H264数据
        IngenicPutH264DataToBuffer(&stream);
        
        // 释放流缓冲区
        ret = IMP_Encoder_ReleaseStream(CH0_INDEX, &stream);
        if (ret < 0) {
            IMP_LOG_ERR("IMP_Encoder_ReleaseStream failed
");
        }
    }
    
    return NULL;
}

// 信号处理函数
void HandleSig(int signo)
{
    signal(SIGINT, SIG_IGN);
    signal(SIGTERM, SIG_IGN);

    if (SIGINT == signo || SIGTERM == signo) {
        printf("exit program\n");
        stop = 0;
    }
}

int main(int argc, char *argv[])
{
    int s32MainFd;
    struct timespec ts = { 2, 0 };
    pthread_t id, id2;
    int ret;

    // 设置信号处理
    signal(SIGINT, HandleSig);
    signal(SIGTERM, HandleSig);

    // 初始化环形缓冲区
    ringmalloc(300 * 1024);

    printf("Ingenic RTSP server START\n");
    
    // 初始化系统
    ret = sample_system_init();
    if (ret < 0) {
        printf("sample_system_init failed\n");
        return -1;
    }
    
    // 初始化FrameSource
    ret = sample_framesource_init();
    if (ret < 0) {
        printf("sample_framesource_init failed\n");
        sample_system_exit();
        return -1;
    }
    
    // 初始化编码器
    ret = sample_encoder_init();
    if (ret < 0) {
        printf("sample_encoder_init failed\n");
        sample_framesource_exit();
        sample_system_exit();
        return -1;
    }
    
    // 绑定FrameSource和编码器
    ret = IMP_System_Bind(&chn[CH0_INDEX].framesource_chn, &chn[CH0_INDEX].imp_encoder);
    if (ret < 0) {
        printf("IMP_System_Bind failed\n");
        sample_encoder_exit();
        sample_framesource_exit();
        sample_system_exit();
        return -1;
    }
    
    // 启动视频流
    ret = sample_framesource_streamon();
    if (ret < 0) {
        printf("sample_framesource_streamon failed\n");
        IMP_System_UnBind(&chn[CH0_INDEX].framesource_chn, &chn[CH0_INDEX].imp_encoder);
        sample_encoder_exit();
        sample_framesource_exit();
        sample_system_exit();
        return -1;
    }
    
    // 创建编码线程
    pthread_create(&id, NULL, EncodeThread, NULL);

    // 初始化RTSP服务
    PrefsInit();

    printf("listen for client connecting...\n");

    // 创建RTSP监听端口
    s32MainFd = tcp_listen(SERVER_RTSP_PORT_DEFAULT);

    if (ScheduleInit() == ERR_FATAL) {
        fprintf(stderr,"Fatal: Can't start scheduler %s, %i \nServer is aborting.\n", __FILE__, __LINE__);
        return 0;
    }
    
    // 初始化RTP端口池
    RTP_port_pool_init(RTP_DEFAULT_PORT);

    // 进入主事件循环
    while (stop) {
        nanosleep(&ts, NULL);
        EventLoop(s32MainFd);
    }

    // 停止视频流
    sample_framesource_streamoff();
    
    // 解绑
    IMP_System_UnBind(&chn[CH0_INDEX].framesource_chn, &chn[CH0_INDEX].imp_encoder);
    
    // 清理资源
    sample_encoder_exit();
    sample_framesource_exit();
    sample_system_exit();
    
    // 等待线程结束
    pthread_join(id, NULL);
    
    // 释放环形缓冲区
    ringfree();

    printf("The Server quit!\n");
    return 0;
}